#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

/*
位操作符:& , | ,^ ,~

& -- 按位与
| -- 按位或
^ -- 按位异或
~ -- 按位取反

“位”是指二进制的位
内存中补码运算
"&"的运算是对应的二进制相与，有0则为0；两个同时为1才为1

"|"按位或，对应的二进制或运算，有1则为1，两个同时为0才为0

"^"按位异或，对应的二进制异或运算，相同为0，相异为1
任何整数异或自己 则等于0
任何整数异或0 则等于自己

"~"按位取反，对应的二进制取反运算，原来是1变为0，原来是0变为1
*/

int main()
{
	int a = -5;
	int b = 13;


	//10000000 00000000 00000000 00000101
	//11111111 11111111 11111111 11111010
	//11111111 11111111 11111111 11111011  -5的补码

	//00000000 00000000 00000000 00001101  13的补码


	//按位与
	//int c = a & b;
	//00000000 00000000 00000000 00001001  9  正整数


	//按位或
	//int c = a | b;
	//11111111 11111111 11111111 11111111  补码
	//10000000 00000000 00000000 00000000
	//10000000 00000000 00000000 00000001   原码  -1


	//按位异或
	//int c = a ^ b;
	//11111111 11111111 11111111 11110110  补码
	//10000000 00000000 00000000 00001001  取反加1
	//10000000 00000000 00000000 00001010  原码  -10


	printf("%d\n", c);

	return 0;
}


//按位取反
int main()
{
	int a = 0;
	//00000000 00000000 00000000 00000000

	printf("%d\n", ~a);

	//11111111 11111111 11111111 11111111  补码
	//10000000 00000000 00000000 00000000
	//10000000 00000000 00000000 00000001   原码  -1


	return 0;
}

//位操作符的使用实例

//1.不能创建临时变量（第三个变量），实现两个整数的交换

#include <stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	printf("交换前: a = %d b = %d\n", a, b);

	a = a ^ b;
	b = a ^ b;
	a = a ^ b;//不存在溢出的问题
	
	printf("交换后: a = %d b = %d\n", a, b);
	return 0;
}
/*
异或运算符:相同为0，相异为1

任何整数异或自己 则等于0
任何整数异或0 则等于自己

int a = 3;
int b = 5;

a ^ a = 0;
a ^ 0 = a;
*/


//2.求一个整数储存在内存中的二进制中1的个数？


//方法一: 
//"&"的运算是对应的二进制相与，有0则为0；两个同时为1才为1

#include <stdio.h>

int main()
{
	int n = 0;
	int count = 0;//计数
	scanf("%d", &n);
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if (((n >> i) & 1) == 1)
			count++;

	}
	

	printf("%d\n", count);

	return 0;
}


//方法二:

#include <stdio.h>

int main()
{
	int n = 13; 
	
	int count = 0;

	while (n);
	{
		n = n & (n - 1);
		count++;

	}

	printf("%d\n", count);
	return 0;
}


//测试
//写一个代码，判断n是否是2的次方数//二进制中只有一个1
//8
//15

//1000
//10000

#include <stdio.h>


int main()
{
	int n = 0;
	scanf("%d", &n);

	if ((n & (n - 1)) == 0)
	{
		printf("yes\n");
	}
	else
	{
		printf("no\n");
	}

	return 0;
}



//练习2:二进制的位  置0或者置1
//写一个代码将13的二进制序列的第五位修改为1，然后再改回0


#include <stdio.h>
int main()
{
	int n = 13;
	//00000000 00000000 00000000 00001101
	
	n |= (1 << (5 - 1));
	printf("%d\n", n);
	//00000000 00000000 00000000 00010000
	//00000000 00000000 00000000 00000001
	//1 << 4

	//00000000 00000000 00000000 00011101

	//11111111 11111111 11111111 11101111
	//1 << 4   ~
	n &= (~(1 << (5 - 1)));
	printf("%d\n", n);
	//00000000 00000000 00000000 00001101

	return 0;
}